package ferp.core.game;

import com.google.gson2.Gson;
import ferp.core.player.Player;

import java.util.Random;

/**
 * User: igorgok
 * Date: 2/28/13 4:44 PM
 */
public class Levels
{
  public static synchronized void update(Gson gson, String data)
  {
    if (data != null)
      instance = gson.fromJson(data, Levels.class);
  }

  public static synchronized int getBestMoveDepth(Game g, Settings settings, Player mover)
  {
    if (mover.id() == 0 || g.hand > 0 && (g.bid != null && !g.bid.isPass()))
      return 0;

    Settings.Level level = settings.levels[mover.id() - 1];
    int[][][] table;

    if (g.bid == null || g.bid.isPass())
      table = instance.passing;
    else
      if (g.bid.isMisere())
        table = instance.misere;
      else
        if (g.type == Game.Type.UNKNOWN || g.type == Game.Type.STANDING)
          table = instance.trickingStanding;
        else
          table = instance.trickingOpen;

    int[] probabilities = table[level.ordinal()][g.rounds];
    int depth = 0;

    for (int p : probabilities)
    {
      if (p > 0 && random.nextInt(100) < p)
        return depth;

      ++depth;
    }
    
    return depth;
  }

  private static Levels instance = new Levels();
  private static final Random random = new Random();

  private int[][][] passing = {
      // L0
      {
          {0, 0},
          {0},
          {0},
          {0},
          {},
          {},
          {},
          {},
          {},
          {}
      },
      // L1
      {
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0, 0},
          {0},
          {0},
          {0},
          {},
          {},
      },
      // L2
      {
          {0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0, 0},
          {0},
          {0},
          {},
          {},
      },
          // L3
      {
          {0, 0, 0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0},
          {},
      },
  };

  private int[][][] trickingOpen = {
      // L0
      {
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {}
      },
      // L1
      {
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
      },
      // L2
      {
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0},
          {},
          {},
          {},
          {},
          {},
      },
          // L3
      {
          {0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0},
          {0},
          {},
          {},
          {},
      },
  };

  private int[][][] trickingStanding = {
      // L0
      {
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {}
      },
      // L1
      {
          {0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0, 0},
          {0},
          {0},
          {},
          {},
          {},
          {},
      },
      // L2
      {
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0, 0},
          {0},
          {0},
          {},
          {},
          {},
      },
      // L3
      {
          {0, 0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0},
          {0},
          {},
      },
  };

  private int[][][] misere = {
      // L0
      {
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {},
          {}
      },
      // L1
      {
          {0, 0},
          {0},
          {0},
          {0},
          {},
          {},
          {},
          {},
          {},
          {},
      },
      // L2
      {
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0},
          {0},
          {0},
          {},
          {},
          {},
          {},
      },
          // L3
      {
          {0, 0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0, 0},
          {0, 0, 0, 0, 0},
          {0, 0, 0, 0},
          {0, 0, 0},
          {0, 0},
          {0},
          {},
          {},
      },
  };
}
